using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Reflection;

namespace OracleInternal.SqlAndPlsqlParser
{
	internal class OracleSqlEarleyParserGrammarDefinition : EarleyParserGrammarDefinition
	{
		internal int m_vIdentifierSymbolIndex;

		protected int m_vStringLiteralSymbolIndex;

		protected int m_vDigitsSymbolIndex;

		private static readonly object m_vObjectLock = new object();

		private static OracleSqlEarleyParserGrammarDefinition s_vInstance = null;

		private static OracleMbEarleyRulesPriorityDescriptor[] s_cRulesPriorityDescriptors;

		public static OracleSqlEarleyParserGrammarDefinition Instance
		{
			get
			{
				lock (m_vObjectLock)
				{
					if (s_vInstance == null)
					{
						s_vInstance = new OracleSqlEarleyParserGrammarDefinition(GetRulesSet("Oracle.ManagedDataAccess.src.SqlParser.Resources.SQLPLSQL.zip"));
					}
				}
				return s_vInstance;
			}
		}

		public override OracleMbEarleyRulesPriorityDescriptor[] RulesPriorityDescriptors => s_cRulesPriorityDescriptors;

		protected OracleSqlEarleyParserGrammarDefinition(Set<RuleTuple> rules)
			: base(rules)
		{
			m_vIdentifierSymbolIndex = m_vSymbolIndexes["identifier"];
			m_vStringLiteralSymbolIndex = m_vSymbolIndexes["string_literal"];
			m_vDigitsSymbolIndex = m_vSymbolIndexes["digits"];
		}

		protected override void InitializeSpecialWords()
		{
			ParserGrammarReservedWordsAndKeywords parserGrammarReservedWordsAndKeywords = OracleSqlGrammarReservedWordsAndKeywords.s_vInstance;
			string[] reservedWords = parserGrammarReservedWordsAndKeywords.ReservedWords;
			foreach (string key in reservedWords)
			{
				int num = m_vQuotedSymbolIndexes[key];
				if (num >= 0)
				{
					m_vSymbolsFlags[num] |= 288;
				}
			}
			reservedWords = parserGrammarReservedWordsAndKeywords.Keywords;
			foreach (string key2 in reservedWords)
			{
				int num = m_vQuotedSymbolIndexes[key2];
				if (num >= 0)
				{
					m_vSymbolsFlags[num] |= 272;
				}
			}
			parserGrammarReservedWordsAndKeywords = OraclePlsqlGrammarReservedWordsAndKeywords.s_vInstance;
			reservedWords = parserGrammarReservedWordsAndKeywords.ReservedWords;
			foreach (string key3 in reservedWords)
			{
				int num = m_vQuotedSymbolIndexes[key3];
				if (num >= 0)
				{
					m_vSymbolsFlags[num] |= 544;
				}
			}
			reservedWords = parserGrammarReservedWordsAndKeywords.Keywords;
			foreach (string key4 in reservedWords)
			{
				int num = m_vQuotedSymbolIndexes[key4];
				if (num >= 0)
				{
					m_vSymbolsFlags[num] |= 528;
				}
			}
		}

		public override bool LookaheadOK(int lookAheadSymbol, int symbolIndex, bool symbolCouldBeIdentifier)
		{
			if (lookAheadSymbol < 0 || symbolIndex < 0)
			{
				return true;
			}
			if ((m_vSymbolsFlags[lookAheadSymbol] & 1) == 0)
			{
				return CanBePrediction(lookAheadSymbol, symbolIndex, symbolCouldBeIdentifier);
			}
			if (lookAheadSymbol != symbolIndex)
			{
				if (symbolCouldBeIdentifier)
				{
					return lookAheadSymbol == m_vIdentifierSymbolIndex;
				}
				return false;
			}
			return true;
		}

		public override bool CanBePrediction(int symbol, int firstSymbol, bool firstSymbolCouldBeIdentifier)
		{
			HashSet<int> hashSet = m_vHasPathToFirstSymbolTable[symbol];
			if (!hashSet.Contains(firstSymbol))
			{
				if (firstSymbolCouldBeIdentifier)
				{
					return hashSet.Contains(m_vIdentifierSymbolIndex);
				}
				return false;
			}
			return true;
		}

		public override void GetTokensInfo(LexerToken token, out int symbolIndex, out bool symbolCouldBeIdentifier)
		{
			symbolCouldBeIdentifier = false;
			switch (token.m_vType)
			{
			case Token.DIGITS:
				symbolIndex = m_vDigitsSymbolIndex;
				break;
			case Token.DQUOTED_STRING:
				symbolIndex = m_vIdentifierSymbolIndex;
				break;
			case Token.QUOTED_STRING:
				symbolIndex = m_vStringLiteralSymbolIndex;
				break;
			case Token.IDENTIFIER:
				symbolIndex = m_vQuotedSymbolIndexes[token.m_vContent];
				if (symbolIndex < 0)
				{
					symbolIndex = m_vIdentifierSymbolIndex;
				}
				else if ((m_vSymbolsFlags[symbolIndex] & 0x20) == 0)
				{
					symbolCouldBeIdentifier = true;
				}
				break;
			case Token.OPERATION:
				symbolIndex = m_vQuotedSymbolIndexes[token.m_vContent];
				break;
			default:
				symbolIndex = -1;
				break;
			}
		}

		protected static Set<RuleTuple> GetRulesSet(string resource)
		{
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resource);
			using GZipStream gZipStream = new GZipStream(stream, CompressionMode.Decompress);
			MemoryStream memoryStream = new MemoryStream();
			gZipStream.CopyTo(memoryStream);
			memoryStream.Position = 0L;
			InputStream inputStream = new InputStream(memoryStream);
			return (inputStream != null) ? RuleTuple.ReadUnifiedRules(inputStream) : null;
		}

		static OracleSqlEarleyParserGrammarDefinition()
		{
			OracleMbEarleyRulesPriorityDescriptor[] array = new OracleMbEarleyRulesPriorityDescriptor[14];
			OracleMbEarleyRulesPriorityDescriptor oracleMbEarleyRulesPriorityDescriptor = new OracleMbEarleyRulesPriorityDescriptor
			{
				m_vHeadSymbol = "expr",
				m_vFirstRHSSymbols = new string[4]
				{
					"type_constructor_expression",
					"object_access_expression",
					"function_expression",
					"simple_expression"
				}
			};
			array[0] = oracleMbEarleyRulesPriorityDescriptor;
			oracleMbEarleyRulesPriorityDescriptor = new OracleMbEarleyRulesPriorityDescriptor
			{
				m_vHeadSymbol = "col_properties",
				m_vFirstRHSSymbols = new string[5]
				{
					"supplemental_logging_props",
					"virtual_column_definition",
					"column_definition",
					"out_of_line_ref_constraint",
					"out_of_line_constraint"
				}
			};
			array[1] = oracleMbEarleyRulesPriorityDescriptor;
			oracleMbEarleyRulesPriorityDescriptor = new OracleMbEarleyRulesPriorityDescriptor
			{
				m_vHeadSymbol = "unconstrained_type_wo_datetime",
				m_vFirstRHSSymbols = new string[2]
				{
					"link_expanded_n",
					"'SYS_REFCURSOR'"
				}
			};
			array[2] = oracleMbEarleyRulesPriorityDescriptor;
			oracleMbEarleyRulesPriorityDescriptor = new OracleMbEarleyRulesPriorityDescriptor
			{
				m_vHeadSymbol = "simple_expression",
				m_vFirstRHSSymbols = new string[8]
				{
					"column",
					"identifier",
					"'CONNECT_BY_ISLEAF'",
					"'CONNECT_BY_ISCYCLE'",
					"'ROWNUM'",
					"'ROWID'",
					"'CONNECT_BY_ROOT'",
					"'NULL'"
				}
			};
			array[3] = oracleMbEarleyRulesPriorityDescriptor;
			oracleMbEarleyRulesPriorityDescriptor = new OracleMbEarleyRulesPriorityDescriptor
			{
				m_vHeadSymbol = "function_expression",
				m_vFirstRHSSymbols = new string[3]
				{
					"function_call",
					"count",
					"function"
				}
			};
			array[4] = oracleMbEarleyRulesPriorityDescriptor;
			oracleMbEarleyRulesPriorityDescriptor = new OracleMbEarleyRulesPriorityDescriptor
			{
				m_vHeadSymbol = "function",
				m_vFirstRHSSymbols = new string[5]
				{
					"object_reference_function",
					"user_defined_function",
					"single_row_function",
					"analytic_function",
					"aggregate_function"
				}
			};
			array[5] = oracleMbEarleyRulesPriorityDescriptor;
			oracleMbEarleyRulesPriorityDescriptor = new OracleMbEarleyRulesPriorityDescriptor
			{
				m_vHeadSymbol = "comparison_condition",
				m_vFirstRHSSymbols = new string[3]
				{
					"simple_comparison_condition",
					"group_comparison_condition",
					"between_condition"
				}
			};
			array[6] = oracleMbEarleyRulesPriorityDescriptor;
			oracleMbEarleyRulesPriorityDescriptor = new OracleMbEarleyRulesPriorityDescriptor
			{
				m_vHeadSymbol = "analytic_function",
				m_vFirstRHSSymbols = new string[10]
				{
					"a_f",
					"max",
					"min",
					"sum",
					"lead",
					"lag",
					"listagg",
					"first_last_value",
					"nth_value",
					"count"
				}
			};
			array[7] = oracleMbEarleyRulesPriorityDescriptor;
			oracleMbEarleyRulesPriorityDescriptor = new OracleMbEarleyRulesPriorityDescriptor
			{
				m_vHeadSymbol = "windowing_clause[31,73)",
				m_vFirstRHSSymbols = new string[2]
				{
					"expr",
					"'UNBOUNDED'"
				}
			};
			array[8] = oracleMbEarleyRulesPriorityDescriptor;
			oracleMbEarleyRulesPriorityDescriptor = new OracleMbEarleyRulesPriorityDescriptor
			{
				m_vHeadSymbol = "windowing_clause[81,123)",
				m_vFirstRHSSymbols = new string[2]
				{
					"expr",
					"'UNBOUNDED'"
				}
			};
			array[9] = oracleMbEarleyRulesPriorityDescriptor;
			oracleMbEarleyRulesPriorityDescriptor = new OracleMbEarleyRulesPriorityDescriptor
			{
				m_vHeadSymbol = "select_term",
				m_vFirstRHSSymbols = new string[2]
				{
					"aliased_expr",
					"expr"
				}
			};
			array[10] = oracleMbEarleyRulesPriorityDescriptor;
			oracleMbEarleyRulesPriorityDescriptor = new OracleMbEarleyRulesPriorityDescriptor
			{
				m_vHeadSymbol = "ty_def",
				m_vFirstRHSSymbols = new string[2]
				{
					"tbl_ty_def",
					"array_ty_def"
				}
			};
			array[11] = oracleMbEarleyRulesPriorityDescriptor;
			oracleMbEarleyRulesPriorityDescriptor = new OracleMbEarleyRulesPriorityDescriptor
			{
				m_vHeadSymbol = "datetime_expression[1923,1939)",
				m_vFirstRHSSymbols = new string[3]
				{
					"expr",
					"string_literal",
					"'DBTIMEZONE'"
				}
			};
			array[12] = oracleMbEarleyRulesPriorityDescriptor;
			oracleMbEarleyRulesPriorityDescriptor = new OracleMbEarleyRulesPriorityDescriptor
			{
				m_vHeadSymbol = "excptn_choice",
				m_vFirstRHSSymbols = new string[2]
				{
					"dotted_name",
					"'OTHERS'"
				}
			};
			array[13] = oracleMbEarleyRulesPriorityDescriptor;
			s_cRulesPriorityDescriptors = array;
		}
	}
}
